package com.suixun.util;

import com.suixun.util.encode.EncodeUtils;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.security.GeneralSecurityException;

/**
 * 可逆加密
 *
 * @author <a href="mailto:hellmash@gmail.com">hellmash</a>
 * @version create on 2015-05-17 11:13
 */
public class CryptoUtil {
    private static final String AES = "AES";

    public static final byte[] GUANG_AES_KEY = new byte[] {
            -11, -59, 106, -53, -14, 18, -4, 64, -58, 92, 95, 101, 20, 90, 85, 63};

    public static final byte[] GUANG_DES_KEY = new byte[] {
            -5, -36, -83, 115, 14, -111, -42, -9
    };

    /**
     * 使用AES解密Base64编码的加密字符串, 返回原始字符串.
     *
     * @param input Base64编码的加密字符串
     * @param keyBytes 符合AES要求的密钥
     */
    public static String aesDecryptFromBase64(String input, byte[] keyBytes) {
        byte[] decryptResult = aes(EncodeUtils.base64Decode(input), keyBytes, Cipher.DECRYPT_MODE);
        return new String(decryptResult);
    }

    /**
     * 使用AES加密原始字符串, 返回Base64 urlsafe编码的结果.
     *
     * @param input 原始输入字符串
     * @param keyBytes 符合AES要求的密钥
     */
    public static String aesEncryptToBase64UrlSafe(String input, byte[] keyBytes) {
        byte[] encryptResult = aes(input.getBytes(), keyBytes, Cipher.ENCRYPT_MODE);
        return EncodeUtils.base64UrlSafeEncode(encryptResult);
    }

    /**
     * 使用AES加密或解密无编码的原始字节数组, 返回无编码的字节数组结果.
     *
     * @param inputBytes 原始字节数组
     * @param keyBytes 符合AES要求的密钥
     * @param mode Cipher.ENCRYPT_MODE 或 Cipher.DECRYPT_MODE
     */
    private static byte[] aes(byte[] inputBytes, byte[] keyBytes, int mode) {
        try {
            SecretKey secretKey = new SecretKeySpec(keyBytes, AES);
            Cipher cipher = Cipher.getInstance(AES);
            cipher.init(mode, secretKey);
            return cipher.doFinal(inputBytes);
        } catch (GeneralSecurityException e) {
            throw convertRuntimeException(e);
        }
    }

    private static IllegalStateException convertRuntimeException(GeneralSecurityException e) {
        return new IllegalStateException("Security exception", e);
    }
}
